home *** CD-ROM | disk | FTP | other *** search
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ** PROGRAM TITLE THE RECIPE SYSTEM
- **
- ** Translated by: Raymond E. Penley from the BASIC
- ** version into Pascal.
- **
- ** DATE WRITTEN: 23 FEB 1980
- **
- ** WRITTEN FOR: Computer hobbyists
- **
- ** PROGRAM SUMMARY:
- **
- ** The recipe system stores recipes and retrives recipies
- ** by means of a numeric key that represents the foods
- ** used in the meal. Foods are divided into four
- ** categories according to their nutritional value.
- ** For more comments see the original program.
- **
- ** INPUT AND OUTPUT FILES:
- ** RCPDAT.XXX and RCPDAT.YYY
- ** - the DATA and the backup files
- ** RCPDAT.MST - the statistics file
- **
- ** MODIFICATION RECORD:
- ** 28 Feb 80 -
- ** 2 Jun 80 -Rewritten for Pascal/Z v 3.0
- ** 8 Jun 80 -Rewrote SCAN
- **
- ** ORIGINAL PROGRAM:
- ** T.G.LEWIS, 'THE MIND APPLIANCE'
- ** HAYDEN BOOK COMPANY
- **
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- PROGRAM RECIPE;
-
- CONST
- default = 80; (* Default length for strings *)
- str_len = 73; (* Length of a recipe line plus one char *)
- StrMax = 255; (* Max Length of strings allowed *)
- EOS = '|'; (* End of String marker *)
- Master = 'RCPDAT.MST';
- Tab20 = 20 ;
- Tab15 = 15 ;
- INPUT = 0; (***** PASCAL/Z ver 3.n *****)
-
- TYPE
- ALFA = STRING 10 ;
- BYTE = 0..255;
- LINE = string default;
- Mstring = string 255 ;
- DataType = record
- MR, (* MaxRecords *)
- CR : integer; (* Curr_Rcds *)
- F1, (* current_ID *)
- F2, (* backup_ID *)
- date : string 14 (* last_update *)
- end;
- S$0 = STRING 0 ; { zero length string }
- S$255 = STRING 255 ; { max string length }
-
- VAR
- adding_recipies, (* adding recipies state flag *)
- comanding, (* Command mode flag *)
- done (* Program execution flag *)
- : boolean;
- bell, (* ASCII bell char *)
- ch,
- command : char;
- data : datatype;
- End_of_File, (* End of File flag *)
- End_of_Text (* End of Text flag *)
- : boolean;
- error_flag : BYTE;
- CRT_width, (* Width of video display *)
- Curr_Rcds, (* No. of current active records *)
- Hash, (* Computed Index value of Recipe *)
- ix, (* global indexer *)
- Last, (* length of last line read *)
- MaxRecords, (* Maximum records allowed *)
- TTY_width (* Width of teletype device *)
- : integer;
- Last_update : string 14; (* date of last file update *)
- matrix : packed array[1..5] of LINE;
- (* File Identifiers <FID> *)
- current_ID, (* Current file ID *)
- backup_ID :string 14; (* Back up file ID *)
- (* File descriptor <FCB> *)
- stats :FILE of datatype;
-
- {$C- [ctrl-c checking OFF]}
- {$F- [floating point error checking OFF]}
- {$M- [integer mult & divd checking OFF]}
-
- (*---Required for Pascal/Z supplied string functions---*)
- FUNCTION LENGTH(X: S$255): INTEGER; EXTERNAL;
- PROCEDURE SETLENGTH(VAR X :S$0; Y :INTEGER); EXTERNAL;
-
-
-
- (*----------------------------------------------*)
- (* DISK I/O *)
- (*----------------------------------------------*)
-
-
-
- Procedure OPEN_MASTER;
- begin
- (* OPEN file RECIPE.MST for READ assign stats *)
- RESET(master, stats);
- READ(stats, data );
- with data do begin
- MaxRecords := MR;
- Curr_Rcds := CR;
- current_ID := F1;
- backup_ID := F2;
- last_update := date
- end(* with *)
- end;
-
- Procedure UPDATE_MASTER;
- begin
- (* OPEN file RECIPE.MST for WRITE assign stats *)
- REWRITE(master, stats);
- with data do begin
- MR := MaxRecords;
- CR := Curr_Rcds;
- F1 := current_ID ;
- F2 := backup_ID ;
- date := last_update
- end(* with *);
- WRITE(stats, data )
- end;
-
- Procedure GETLINE(VAR fx : TEXT;
- VAR INBUFF : LINE );
- { This Procedure gets a line of text from a disk file.
- Returns:
- End_of_Text = true if the input buffer length
- exceeded.
- End_of_File = true if EOF
- INBUFF = input buffer }
- VAR CH : CHAR;
- ix, length : integer;
- begin
- length := 0;
- End_of_Text := FALSE;
- SETLENGTH(INBUFF,0);
- WHILE NOT EOF(fx) AND (CH <> EOS) DO
- begin
- If length < str_len then
- begin(* valid *)
- READ(fx, CH );
- length := SUCC(length);
- APPEND(INBUFF,CH)
- end(* If *)
- ELSE
- End_of_Text := TRUE;
- end(* WHILE *);
- If length >= last then
- last:=length
- Else
- REPEAT
- APPEND(INBUFF,EOS);
- last := PRED(last)
- UNTIL last=length;
- End_of_File := EOF(fx)
- end(*---of GetLine---*);
-
- Procedure PUTLINE( VAR fx : TEXT;
- VAR this : LINE );
- { This Procedure puts a line of text to a disk file }
- VAR CH : char;
- pos : integer;
- begin
- pos := 0;
- REPEAT
- pos := SUCC(pos);
- CH := this[ pos ];
- If CH <> EOS then Write(fx, CH)
- UNTIL (CH = EOS) OR (pos = str_len);
- Write(fx, EOS) (* Mark the End of String *)
- end(*---of PUTLINE---*);
-
- Procedure PUT_RECORD( VAR fx : TEXT;
- VAR Index : integer );
- VAR jx : integer;
- begin
- Writeln(fx, Index:5);
- For jx:=1 to 5 do
- PUTLINE(fx,matrix[jx] );
- end(*---of PUT_RECORD---*);
-
- Procedure GET_RECORD(VAR fx : TEXT;
- VAR Index : integer );
- VAR JJ : integer;
- begin
- READLN (fx, Index);
- FOR JJ := 1 to 5 DO
- GETLINE(fx,matrix[JJ]);
- end(*---of GET_RECORD---*);
-
-
-
- (*----------------------------------------------*)
- (* CONSOLE I/O *)
- (*----------------------------------------------*)
-
-
-
- Procedure KEYIN(VAR CIX : char); EXTERNAL;
- (*---Single char input directly from keyboard---*)
-
- Procedure PRINT(this : Mstring);
- (* Print the string 'this' until EOS *)
- VAR
- CH : CHAR;
- pos : integer;
- begin
- pos := 0;
- REPEAT
- pos := SUCC(pos);
- CH := this[ pos ];
- If CH <> EOS then Write(CH)
- UNTIL (CH = EOS) OR (pos = str_len);
- Writeln
- end(*---of PRINT---*);
-
- Procedure SCAN( VAR Arg_string : LINE ;
- count : integer ;
- VAR status : BYTE );
- (*----------------------------------------------*)
- (* version: 3.1 /8 JUN 80/ by R.E.Penley *)
- (*----------------------------------------------*
- ** Scan will scan your input line and return:
- STATUS:
- 0 -OK, valid inputs
- 1 -an attempt was made to exceed "count"
- characters - so I truncated the string at
- count chars for you.
- 2 -an invalid character was detected.
- You figure out what to do with it!
- LENGTH(arg string) = 0 means a null string input.
- **
- Valid Alphanumeric chars are the ASCII char set
- starting at the space [ CHR(32) ] and
- ending at the tilde [ CHR(126) ].
- *----------------------------------------------*
- GLOBAL StrMax = 255;
- BYTE = 0..255;
- LINE = STRING Default;
- *----------------------------------------------*)
- VAR loop : (scanning, found, notfound);
- ix : 1..StrMax;
- begin
- { return status = 0 if no errors detected. }
- status := 0;
- { return status = 1 if requested length is exceeded }
- If LENGTH(arg_string) > count then
- begin
- status := 1;
- SETLENGTH(arg_string,count)
- end;
- loop := scanning;
- ix := 1;
- While (loop=scanning) do
- { return status = 2 if any invalid chars found }
- begin
- If ix > LENGTH(arg_string) then
- loop := notfound{excellent - no invalid chars}
- Else
- If arg_string[ix] IN [' '..'~'] then{good show - keep going}
- ix := SUCC(ix)
- Else
- begin
- loop := found{invalid char};
- status := 2
- end
- end{while}
- End(*---of SCAN 3.1---*);
-
-
-
- (*----------------------------------------------*)
- (* UTILITY ROUTINES *)
- (*----------------------------------------------*)
-
-
- Function YORN : boolean ;
- {
- YES/NO INPUT MODULE
- Returns:
- TRUE FOR 'Y' or 'y' INPUT
- FALSE FOR 'N' or 'n' INPUT
- }
- VAR
- ans : ALFA;
- valid : boolean;
- begin
- REPEAT
- valid := true;
- READ(ans);
- CASE ans[1] of
- 'Y','y': YORN := true;
- 'N','n': YORN := false;
- Else: begin
- valid := false;
- Writeln(BELL, 'Please answer ''Y'' or ''N'' ')
- end
- end{case}
- Until valid{response}
- End(*---of YORN---*);
-
- Procedure CLEAR;
- (* Device dependent procedure *)
- begin
- Write( CHR(26) )
- end;
-
- Procedure SKIP(L1 : integer);
- VAR ix : integer;
- begin
- FOR ix:=1 to L1 do Writeln
- end;
-
- Procedure PAUSE;
- CONST sign = 'Type return to continue:';
- VAR dummy : char;
- begin
- SKIP(4);
- Write(sign);
- Readln(dummy)
- end;
-
- Procedure BREAK;
- begin
- CLEAR;
- SKIP(5)
- end;
-
- Procedure DRAW(picture : Mstring; count : integer );
- { Draw a picture count times }
- VAR ix : integer;
- begin
- FOR ix:=1 to count DO Write( picture );
- Writeln
- end(*---of DRAW---*);
-
- Procedure ShowRecipe;
- VAR JJ : integer;
- begin
- FOR JJ := 1 to 5 DO
- PRINT(matrix[JJ]) ;
- Writeln
- end(*--of ShowRecipe--*);
-
- Procedure Display_One(VAR Index : integer);
- begin
- Writeln;
- Writeln( 'Recipe #', Index:5 );
- Writeln;
- DRAW( '- ', 20);
- Writeln;
- ShowRecipe;
- skip(4)
- end(*---of Display_One---*);
-
-
- (*----------------------------------------------*
- * ADD MODULE *
- *----------------------------------------------*)
-
- {$C+ [ctrl-c checking ON]}
-
- Procedure InputFeatures(VAR I : integer);
- (******************************************
- * Input Features of Recipe *
- ******************************************)
- (*
- RETURNS:
- Hash value computed for various choices
- **)
- CONST Msg1 = 'None of these' ;
- VAR F, D, V, P :integer;
-
- Function QUIRY(X2 : integer) : integer;
- VAR ix : integer;
- cix : char;
- begin
- REPEAT
- Writeln;
- Write('Enter Choice (1 to', X2:2, ') ');
- KEYIN(cix);write(cix);
- ix := (ORD(cix) - ORD('0'))
- UNTIL (ix>=1) AND (ix<=X2) ;
- QUIRY := ix
- end;
-
- begin
- Writeln;
- Writeln( ' Enter number of choice :');
- Writeln;
- Writeln( ' ':Tab15, 'Fibre Foods' );
- Writeln;
- Writeln( ' ':Tab15, '1. Bread (flour)');
- Writeln( ' ':Tab15, '2. Oats' );
- Writeln( ' ':Tab15, '3. Rice');
- Writeln( ' ':Tab15, '4. Corn' );
- Writeln( ' ':Tab15, '5. Macaroni');
- Writeln( ' ':Tab15, '6. Noodles' );
- Writeln( ' ':Tab15, '7. Spaghetti');
- Writeln( ' ':Tab15, '8. ', Msg1 );
- F := QUIRY(8);
- BREAK;
- Writeln;
- Writeln( ' ':Tab15, 'Protein' );
- Writeln;
- Writeln( ' ':Tab15, '1. Beef');
- Writeln( ' ':Tab15, '2. Poultry' );
- Writeln( ' ':Tab15, '3. Fish');
- Writeln( ' ':Tab15, '4. Eggs' );
- Writeln( ' ':Tab15, '5. Beans');
- Writeln( ' ':Tab15, '6. Nuts' );
- Writeln( ' ':Tab15, '7. ', Msg1 );
- P := QUIRY(7);
- BREAK;
- Writeln;
- Writeln( ' ':Tab15, 'Dairy' );
- Writeln;
- Writeln( ' ':Tab15, '1. Milk');
- Writeln( ' ':Tab15, '2. Cheese' );
- Writeln( ' ':Tab15, '3. Cottage Cheese');
- Writeln( ' ':Tab15, '4. Cream' );
- Writeln( ' ':Tab15, '5. Sour Cream');
- Writeln( ' ':Tab15, '6. ', Msg1 );
- D := QUIRY(6);
- BREAK;
- Writeln;
- Writeln( ' ':Tab15, 'Fruits and Vegetables' );
- Writeln;
- Writeln( ' ':Tab15, '1. Citrus');
- Writeln( ' ':Tab15, '2. Melon' );
- Writeln( ' ':Tab15, '3. Juices');
- Writeln( ' ':Tab15, '4. Greens' );
- Writeln( ' ':Tab15, '5. Yellows & Reds' );
- Writeln( ' ':Tab15, '6. ', Msg1 );
- V := QUIRY(6);
- CLEAR;
-
- {*****************************************}
- { Compute the index value by assigning }
- { a weight to each digit in the set. }
- {*****************************************}
-
- I := 252*F + 36*P + 6*D + V - 295
-
- {******************************************}
-
- end{of InputFeatures};
-
-
-
- Procedure InputRecipe;
- (*---------------------------------------*
- * Input individual recipies *
- *---------------------------------------*)
- LABEL
- 99; (*---EXIT---*)
- CONST
- prompt = '>';
- VAR
- state : (absent, done, adding) ;
- ix, jx : integer;
- temp : STRING 14;
- One_Line : LINE;
- YES : boolean;
- (* File descriptors <FCB> *)
- current,
- backup : TEXT;
-
- PROCEDURE CORRECT;
- CONST question = 'Are there any corrections to be made';
- msg1 = 'Enter <cr> return if correct or Reenter the line';
- begin
- REPEAT
- BREAK;
- Writeln(bell,' ':(TTY_width DIV 2) -10, 'HERE IS YOUR RECIPE');
- Writeln;
- ShowRecipe;
- Writeln;
- Writeln(question);
- YES := YORN;
- If YES then
- begin
- BREAK;
- Writeln(msg1);
- Writeln;
- For ix:=1 to 5 do
- begin
- REPEAT
- PRINT(matrix[ix]);
- SETLENGTH(one_line,0);
- READLN(one_Line);
- SCAN(one_Line, str_len - 1, error_flag);
- If (LENGTH(one_Line) > 0) AND (error_flag=0) then
- begin
- APPEND(one_Line,EOS);
- matrix[ix] := one_Line
- end;
- If error_flag IN [1,2] then
- CASE error_flag of
- 1: writeln('Invalid length, please reinput');
- 2: writeln('Alpha numerics only, please reinput')
- End{case}
- Until error_flag=0;
- end{for}
- end(* If *)
- Until not YES
- end(*---of Correct---*);
-
- Function adding_desired : boolean ;
- CONST addquest = 'Do you want to ADD recipies? ';
- begin
- PAUSE;
- BREAK;
- Write(addquest);
- adding_desired := YORN;
- CLEAR
- end;
-
- begin(*---InputRecipe---*)
- If not adding_desired then{EXIT}goto 99;
- adding_recipies := true ;
- state := adding ;
- (* OPEN file backup_ID for WRITE assign backup *)
- REWRITE(backup_ID, backup);
- (* OPEN file current_ID for READ assign current *)
- RESET(current_ID, current);
-
- {$C- [ctrl-c checking OFF]}
-
- If NOT EOF(current) then
- begin(* COPY current to back_up *)
- ix := 0 ;
- While ix < Curr_Rcds do
- begin
- ix := SUCC(ix);
- GET_RECORD(current,hash);
- PUT_RECORD(backup,hash)
- end(* while *)
- end(* COPY current to back_up *);
-
- {$C+ [ctrl-c checking ON]}
-
- (*---Input/Enter additional recipies until done---*)
- (*---or curr_records > Max_Records allowed ---*)
-
- REPEAT
- If Curr_Rcds > MaxRecords then
- state := done
- Else
- begin(*---add more recipies---*)
- Writeln('Identify Recipe with features. First ');
- InputFeatures(HASH);
- BREAK;
- Writeln('Now Enter 5 lines of the recipe');
- Writeln;
- For jx := 1 to 5 DO
- begin
- REPEAT
- write(prompt);
- SETLENGTH(one_line,0);
- READLN(one_line);
- SCAN(one_Line, str_len - 1, error_flag);
- If error_flag IN [1,2] then
- CASE error_flag of
- 1: writeln('Invalid length, please reinput');
- 2: writeln('Alpha numerics only, please reinput')
- End{case}
- Until error_flag=0;
- APPEND(one_Line,EOS);
- matrix[jx] := one_Line
- end{For};
- Correct(* if required *);
- Curr_Rcds := SUCC(Curr_Rcds);
- PUT_RECORD(backup,hash);
- If not adding_desired then state := done;
- end(*---add more recipies---*)
- UNTIL state<>adding;
- (*--------------------------------------------*)
- (* SWAP file ID`s *)
- (* Back Up file is now the Current file *)
- (*--------------------------------------------*)
- temp := backup_ID;
- backup_ID := current_ID;
- current_ID := temp;
-
- UPDATE_MASTER;(*--status file--*)
-
- 99:(* Come here if do not desire to add *)
- End{*--of InputRecipe--*};
-
-
- (*--------------------------------------*)
- (* DUMP/FIND MODULE *)
- (*--------------------------------------*)
-
- PROCEDURE FILE_SCAN ;
- (*
- GLOBAL
- MaxRecords = maximum allowed records
- Curr_Rcds = # of recipes in file
- *)
- VAR
- state : (absent, found, searching) ;
- Rcds,
- index : integer;
- fa : TEXT; (* FCB. File descriptor *)
-
- Procedure DUMP;
- (**********************************)
- (* OUTPUT all Recipes from file *)
- (**********************************)
- begin
- REPEAT
- If Rcds > Curr_Rcds then
- state := absent
- Else
- begin
- Rcds := SUCC(Rcds);
- GET_RECORD(fa,hash);
- Display_One(hash);
- PAUSE
- end(* else *)
- UNTIL state<>searching
- end(*--of DUMP--*);
-
- Procedure FIND;
- (************************************)
- (* Lookup recipes from file *)
- (************************************)
- begin {$C- [ctrl-c checking OFF]}
- InputFeatures(Index);
- REPEAT
- If Rcds > Curr_Rcds then
- state := absent
- Else
- begin
- Rcds := SUCC(Rcds);
- GET_RECORD(fa,hash);
- If HASH=Index then
- begin
- CLEAR;
- Display_One(hash);
- PAUSE
- end
- end(* else *)
- Until state<>searching
- end(*--of Lookup--*); {$C+ [ctrl-c checking ON]}
-
- begin(*---File_Scan---*)
- CLEAR;
- state := absent;
- If adding_recipies then{read in new stats}
- OPEN_MASTER;
- (* OPEN file current_ID for READ assign fa *)
- RESET(current_ID, fa);
- If NOT EOF(fa) then
- If Curr_rcds=0 then
- state := absent
- Else
- begin
- state := searching ;
- Rcds := 1 ;
- CASE command of
- 'O', 'o': DUMP;
- 'F', 'f': FIND
- End{case commmand of}
- end(* else *);
- If state=absent then
- begin
- BREAK;
- Writeln('That''s all the Recipes on File')
- end;
- PAUSE
- end(*---of File_Scan---*);
-
- (*--------------------------------------*)
- (* INITIALIZATION *)
- (*--------------------------------------*)
-
-
- Procedure INIT1;
- begin
- bell := CHR(7) ;
- CRT_width := 80 ;
- TTY_width := 72 ;
- last := str_len ;
- MaxRecords := 75 ;
- (* maximum number of records =
- # BYTES per Record times # of records
- # BYTES per record =
- # chars per line + overhead per line times
- # of lines. ***)
- Curr_Rcds := 0 ;
- Last_Update := 'YY/MM/DD ';
- current_ID := 'RCPDAT.XXX ';
- backup_ID := 'RCPDAT.YYY ';
- adding_recipies := false;
- end;
-
- Procedure INIT2;
- begin
- (* OPEN file `RECIPE.MST` for READ assign stats *)
- RESET(master, stats);
- If EOF(stats) then(* not found *)
- (* OPEN file `RECIPE.MST` for WRITE assign stats *)
- UPDATE_MASTER
- Else
- begin(* READ in data record *)
- READ(stats, data );
- with data do begin
- MaxRecords := MR;
- Curr_Rcds := CR;
- current_ID := F1;
- backup_ID := F2;
- last_update := date
- end(* with *)
- end(* READ in data record *);
- SKIP(5);
- Writeln('Last update of Recipe data file was ', last_update);
- Writeln('File currently consists of ', Curr_Rcds:4, ' Recipies');
- Writeln;
- Write('Please enter todays date <YY/MM/DD> ');
- last_update := ' ';{<<<=== 14 spaces required ===}
- For ix:=1 to 8 do
- begin
- if (ix=3) or (ix=6) then
- ch := '/'
- else
- KEYIN(ch);
- write(ch);
- last_update[ix] := ch
- end{for};
- writeln
- end(*--of INIT2---*);
-
- (*----------------------------------------------*
- * MAIN PROGRAM *
- *----------------------------------------------*)
-
- BEGIN
- INIT1; (* start the initialization process here *)
- CLEAR;
- DRAW('************',TTY_width DIV 12);
- Writeln;
- Writeln( ' ':22, 'The Recipe System');
- Writeln;
- DRAW('************',TTY_width DIV 12);
- INIT2; (* finish init now *)
- { Now execute the program until done }
- done := false;
- While not done do
- begin
- CLEAR;
- DRAW('************',TTY_width DIV 12);
- SKIP(3);
- Writeln( ' ':Tab15, 'Select One of the following:');
- Writeln;
- Writeln( ' ':Tab20, 'I(nput Recipes');
- Writeln( ' ':Tab20, 'O(utput all Recipes');
- Writeln( ' ':Tab20, 'F(ind a Recipe');
- Writeln( ' ':Tab20, 'S(top');
- comanding := true;
- WHILE comanding do
- begin
- comanding := false;
- Writeln;
- Write(' ':(Tab15), 'Enter choice ' );
- KEYIN(command);write(command);
- CASE command of
- 'I', 'i': InputRecipe;
- 'O', 'o',
- 'F', 'f': File_Scan;
- 'S', 's': done := true;
- Else: begin
- Write(BELL);
- comanding := true
- end
- End{ case }
- end{while comanding}
- end{ while not done }
- End{---of Program Recipe---}.